home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / graphics / 3dvect30.arj / XSCALE.INC < prev   
Text File  |  1993-11-18  |  37KB  |  783 lines

  1. ;=========================================================================
  2. ; XSCALE1.ASM by John A. Slagel, jas37876@uxa.cso.uiuc.edu
  3. ; This is some code to do bitmap scaling in VGA Mode X.  It can scale a
  4. ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
  5. ; wide.  It performs complete clipping, with only a small constant amount
  6. ; of time to clip, no matter how huge the image is.  It draws column by
  7. ; column to reduce the number of plane switches, which are slow. The inner
  8. ; column loop has been optimized for no memory accesses, except to read or
  9. ; write a pixel.  This uses MASM 5.1 features, and can be compiled in any
  10. ; memory model by changing the .MODEL line, but make sure that you always
  11. ; pass a far pointer to the bitmap data, regardless of memory model.
  12. ; C-callable as:
  13. ;   void XSCALE1( int X, int Y, int DW, int DY,
  14. ;                     int SW, int SH, void far * Bitmap );
  15. ; X,Y   are the upper left-hand coordinates of where to draw the bitmap.
  16. ; DW,DH are the width and height of the SCALEed bitmap
  17. ; SW,SH are the width and height of the source bitmap.
  18. ; Bitmap is a pointer to the bitmap bits.
  19. ;
  20. ; Routine has been modified for 32 bit protected mode by John McCarthy.
  21. ; John McCarthy thanks John A. Slagel for providing this code, and hopes
  22. ; John A. Slagel is not offended by the changes.
  23. ;
  24. ;==========================================================================
  25.  
  26.             public draw_scale
  27.             public tdraw_scale
  28.             public tdraw_scale4
  29.             public xscale1
  30.             public xscale2
  31.             public xscale4
  32.             public repeat_bitmap
  33.  
  34. ; uses edi esi, destx:word, desty:word,
  35. ; destwidth:word, destheight:word,
  36. ; sourcewidth:word, sourceheight:word,
  37. ; bitmap:far ptr
  38.  
  39. draw_scale:
  40.         mov bitmap,esi
  41.         mov destwidth,ax
  42.         mov destheight,bx
  43.         mov destx,cx
  44.         mov desty,dx
  45.  
  46. xscale1:
  47.         cmp     destwidth, 2        ; if destination width is less than 2
  48.         jl      done                ;     then don't draw it.
  49.  
  50.         cmp     destheight, 2       ; if destination height is less than 2
  51.         jl      done                ;     then don't draw it.
  52.  
  53.         mov     ax, desty           ; if it is completely below the
  54.         cmp     ax, clipbt          ; lower clip bondry,
  55.         jg      done                ;     then don't draw it.
  56.  
  57.         add     ax, destheight      ; if it is above clip boundries
  58.         dec     ax                  ;     then don't draw it.
  59.         cmp     ax, cliptp
  60.         jl      done
  61.  
  62.         mov     ax, destx           ; if it is to the right of the
  63.         mov     cx, cliprt          ; right clip boundry
  64.         cmp     ax, cliprt          ;     then don't draw it.
  65.         jg      done
  66.  
  67.         add     ax, destwidth       ; if it is completely to the left
  68.         dec     ax                  ; of the left clip boundry,
  69.         cmp     ax, cliplt          ;     then don't draw it.
  70.         jl      done
  71.  
  72.         mov     esi, bitmap         ; make esi point to bitmap data
  73.         lodsw                       ; get source x width
  74.         mov     sourcewidth,ax
  75.         lodsw                       ; get source y height
  76.         mov     sourceheight,ax
  77.  
  78.         mov     ax, destwidth       ; clippedwidth is initially set to
  79.         mov     clippedwidth, ax    ; the requested dest width.
  80.  
  81.         shl     ax,1                ; initialize the x decision var
  82.         neg     ax                  ; to be -2*destwidth
  83.         mov     decisionx, ax       ;
  84.  
  85.         mov     ax, destheight      ; clippedheight is initially set to
  86.         mov     clippedheight, ax   ; the requested dest size.
  87.  
  88.         shl     ax,1                ; initialize the y decision var
  89.         neg     ax                  ; to be -2*destheight
  90.         mov     decisiony, ax       ;
  91.  
  92.         movsx   eax, cliptp         ; if y is below the top
  93.         mov     edx, eax            ; clipping boundry, then we don't
  94.         sub     dx, desty           ; need to clip the top, so we can
  95.         js      s notopclip         ; jump over the clipping stuff.
  96.  
  97.         mov     desty, ax           ; this block performs clipping on the
  98.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  99.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  100.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  101.         mov     eax, ecx            ; gonna try to explain what it's doing.
  102.         cdq                         ; but i can tell you what results from
  103.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  104.         idiv    ebx                 ; to start at the right clipped row.
  105.         movsx   edx, sourcewidth    ; y is moved to the top clip
  106.         imul    edx, eax            ; boundry. clippedheight is lowered since
  107.         add     esi, edx            ; we won't be drawing all the requested
  108.         imul    eax, ebx            ; rows. esi is changed to point over
  109.         sub     ecx, eax            ; the bitmap data that is clipped off.
  110.         sub     ecx, ebx            ;
  111.         shl     ecx, 1              ;
  112.         mov     decisiony, cx       ; <end of top clipping block >
  113.  
  114. notopclip:
  115.         mov     ax, desty           ; if the bitmap doesn't extend over the
  116.         add     ax, clippedheight   ; bottom clipping boundry, then we
  117.         dec     ax                  ; don't need to clip the bottom, so we
  118.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  119.         jle     s nobottomclip      ;
  120.  
  121.         mov     ax, clipbt          ; clip off the bottom by reducing the
  122.         sub     ax, desty           ; clippedheight so that the bitmap won't
  123.         inc     ax                  ; extend over the lower clipping
  124.         mov     clippedheight, ax   ; boundry.
  125.  
  126. nobottomclip:
  127.         movsx   eax, cliplt         ; if x is to the left of the
  128.         mov     edx, eax            ; top clipping boundry, then we don't
  129.         sub     dx, destx           ; need to clip the left, so we can
  130.         js      s noleftclip        ; jump over the clipping stuff.
  131.  
  132.         mov     destx, ax           ; this block performs clipping on the
  133.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  134.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  135.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  136.         mov     eax, ecx            ; gonna try to explain what it's doing.
  137.         cdq                         ; but i can tell you what results from
  138.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  139.         idiv    ebx                 ; to start at the right clipped column.
  140.         add     esi, eax            ; x is moved to the left clip
  141.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  142.         sub     ecx, eax            ; we won't be drawing all the requested
  143.         sub     ecx, ebx            ; cols. esi is changed to point over
  144.         shl     ecx, 1              ; the bitmap data that is clipped off.
  145.         mov     decisionx, cx       ; <end of left clipping block >
  146.  
  147. noleftclip:
  148.         mov     ax, destx           ; if the bitmap doesn't extend over the
  149.         add     ax, clippedwidth    ; right clipping boundry, then we
  150.         dec     ax                  ; don't need to clip the right, so we
  151.         cmp     ax, cliprt          ; can jump over the right clip code.
  152.         jle     s noclipright       ;
  153.  
  154.         mov     ax, cliprt          ; clip off the right by reducing the
  155.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  156.         inc     ax                  ; extend over the right clipping
  157.         mov     clippedwidth, ax    ; boundry.
  158.  
  159.         ;calculate starting video address
  160. noclipright:
  161.         movzx   edi, desty          ; we are going to set edi to start point
  162.         imul    edi, xactual/4
  163.         movzx   eax, destx          ; the offset edi is
  164.         mov     cx, ax              ; calculated by:
  165.         shr     ax, 2               ;     di = y*80+x/2
  166.         add     eax, current_page
  167.         add     edi,eax             ; edi is ready!
  168.  
  169.         mov     dx, sc_index+1      ; point the vga sequencer to the map
  170. ;       mov     al, map_mask        ; mask register, so that we only need
  171. ;       out     dx, al              ; to send out 1 byte per column.
  172.  
  173. ;       inc     dx                  ; move to the sequencer's data register.
  174.         and     cx, 3               ; calculate the starting plane. this is
  175.         mov     al, 11h             ; just:
  176.         shl     al, cl              ; plane =  (11h << (x and 3))
  177.         out     dx, al              ; select the first plane.
  178.  
  179.         movzx   ecx, sourcewidth     ; use cx for source width
  180.         mov     xad, ecx
  181.         shl     sourcewidth,1
  182.  
  183.         align   16                  ; since this point gets jumped to a lot,
  184.                                     ; make sure that it is dword aligned.
  185. rowloop:
  186.         push    esi                 ; save the starting source index
  187.         push    edi                 ; save the starting dest index
  188.         push    ax                  ; save the current plane mask
  189.         push    bp                  ; save the current base pointer
  190.  
  191.         mov     cx, clippedheight   ; use al for row counter (0-239)
  192.         mov     bx, decisiony       ; use bx for decision variable
  193.         mov     dx, sourceheight    ; use dx for source height * 2
  194.         shl     dx, 1
  195.         mov     bp, destheight      ; use bp for dest height * 2
  196.         shl     bp, 1
  197.         mov     ah, [esi]           ; get the first source pixel
  198.  
  199.         align   4                   ; common jump point... align for speed.
  200. columnloop:
  201.         mov     [edi], ah           ; draw a pixel
  202.         dec     cx                  ; decrement line counter
  203.         jz      s donewithcol       ; see if we're done with this column
  204.         add     edi, xactual/4      ; go on to the next screen row
  205.         add     bx, dx              ; increment the decision variable
  206.         js      s columnloop        ; draw this source pixel again
  207.  
  208. incsourcerow:
  209.         add     esi, xad            ; move to the next source pixel
  210.         sub     bx, bp              ; decrement the decision variable
  211.         jns     s incsourcerow      ; see if we need to skip another source pixel
  212.         mov     ah, [esi]           ; get the next source pixel
  213.         jmp     s columnloop        ; start drawing this pixel
  214.  
  215. donewithcol:
  216.         pop     bp                  ; restore bp to access variables
  217.         pop     ax                  ; restore al = plane mask
  218.         pop     edi                 ; restore di to top row of screen
  219.         pop     esi                 ; restore si to top row of source bits
  220.  
  221.         rol     al, 1               ; move to next plane
  222.         adc     edi, 0              ; go on to next screen column
  223.         mov     dx, sc_data         ; tell the vga what column we're in
  224.         out     dx, al              ; by updating the map mask register
  225.  
  226.         mov     bx, decisionx       ; use bx for the x decision variable
  227.         add     bx, sourcewidth     ; increment the x decision variable
  228.         js      s nextcol           ; jump if we're still in the same source col.
  229.         mov     dx, destwidth       ; dx = w * 2
  230.         shl     dx, 1
  231. incsourcecol:
  232.         inc     esi                 ; move to next source column
  233.         sub     bx, dx              ; decrement x decision variable
  234.         jns     s incsourcecol      ; see if we skip another source column
  235. nextcol:
  236.         mov     decisionx, bx       ; free up bx for colloop
  237.         dec     clippedwidth        ; if we're not at last column
  238.         jnz     rowloop             ;    then do another column
  239. done:
  240.         ret                         ; we're done!
  241.  
  242. ; draw transparent bitmap.  any bytes that = 0 are skipped
  243.  
  244. tdraw_scale:
  245.         mov bitmap,esi
  246.         mov destwidth,ax
  247.         mov destheight,bx
  248.         mov destx,cx
  249.         mov desty,dx
  250.  
  251. xscale2:
  252.         cmp     destwidth, 2        ; if destination width is less than 2
  253.         jl      s done              ;     then don't draw it.
  254.  
  255.         cmp     destheight, 2       ; if destination height is less than 2
  256.         jl      s done              ;     then don't draw it.
  257.  
  258.         mov     ax, desty           ; if it is completely below the
  259.         cmp     ax, clipbt          ; lower clip bondry,
  260.         jg      s done              ;     then don't draw it.
  261.  
  262.         add     ax, destheight      ; if it is above clip boundries
  263.         dec     ax                  ;     then don't draw it.
  264.         cmp     ax, cliptp
  265.         jl      s done
  266.  
  267.         mov     ax, destx           ; if it is to the right of the
  268.         mov     cx, cliprt          ; right clip boundry
  269.         cmp     ax, cliprt          ;     then don't draw it.
  270.         jg      s done
  271.  
  272.         add     ax, destwidth       ; if it is completely to the left
  273.         dec     ax                  ; of the left clip boundry,
  274.         cmp     ax, cliplt          ;     then don't draw it.
  275.         jl      s done
  276.  
  277.         mov     esi, bitmap         ; make esi point to bitmap data
  278.         lodsw                       ; get source x width
  279.         mov     sourcewidth,ax
  280.         lodsw                       ; get source y height
  281.         mov     sourceheight,ax
  282.  
  283.         mov     ax, destwidth       ; clippedwidth is initially set to
  284.         mov     clippedwidth, ax    ; the requested dest width.
  285.  
  286.         shl     ax,1                ; initialize the x decision var
  287.         neg     ax                  ; to be -2*destwidth
  288.         mov     decisionx, ax       ;
  289.  
  290.         mov     ax, destheight      ; clippedheight is initially set to
  291.         mov     clippedheight, ax   ; the requested dest size.
  292.  
  293.         shl     ax,1                ; initialize the y decision var
  294.         neg     ax                  ; to be -2*destheight
  295.         mov     decisiony, ax       ;
  296.  
  297.         movsx   eax, cliptp         ; if y is below the top
  298.         mov     edx, eax            ; clipping boundry, then we don't
  299.         sub     dx, desty           ; need to clip the top, so we can
  300.         js      s notopclip2        ; jump over the clipping stuff.
  301.  
  302.         mov     desty, ax           ; this block performs clipping on the
  303.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  304.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  305.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  306.         mov     eax, ecx            ; gonna try to explain what it's doing.
  307.         cdq                         ; but i can tell you what results from
  308.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  309.         idiv    ebx                 ; to start at the right clipped row.
  310.         movsx   edx, sourcewidth    ; y is moved to the top clip
  311.         imul    edx, eax            ; boundry. clippedheight is lowered since
  312.         add     esi, edx            ; we won't be drawing all the requested
  313.         imul    eax, ebx            ; rows. esi is changed to point over
  314.         sub     ecx, eax            ; the bitmap data that is clipped off.
  315.         sub     ecx, ebx            ;
  316.         shl     ecx, 1              ;
  317.         mov     decisiony, cx       ; <end of top clipping block >
  318.  
  319. notopclip2:
  320.         mov     ax, desty           ; if the bitmap doesn't extend over the
  321.         add     ax, clippedheight   ; bottom clipping boundry, then we
  322.         dec     ax                  ; don't need to clip the bottom, so we
  323.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  324.         jle     s nobottomclip2
  325.  
  326.         mov     ax, clipbt          ; clip off the bottom by reducing the
  327.         sub     ax, desty           ; clippedheight so that the bitmap won't
  328.         inc     ax                  ; extend over the lower clipping
  329.         mov     clippedheight, ax   ; boundry.
  330.  
  331. nobottomclip2:
  332.         movsx   eax, cliplt         ; if x is to the left of the
  333.         mov     edx, eax            ; top clipping boundry, then we don't
  334.         sub     dx, destx           ; need to clip the left, so we can
  335.         js      s noleftclip2       ; jump over the clipping stuff.
  336.  
  337.         mov     destx, ax           ; this block performs clipping on the
  338.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  339.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  340.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  341.         mov     eax, ecx            ; gonna try to explain what it's doing.
  342.         cdq                         ; but i can tell you what results from
  343.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  344.         idiv    ebx                 ; to start at the right clipped column.
  345.         add     esi, eax            ; x is moved to the left clip
  346.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  347.         sub     ecx, eax            ; we won't be drawing all the requested
  348.         sub     ecx, ebx            ; cols. esi is changed to point over
  349.         shl     ecx, 1              ; the bitmap data that is clipped off.
  350.         mov     decisionx, cx       ; <end of left clipping block >
  351.  
  352. noleftclip2:
  353.         mov     ax, destx           ; if the bitmap doesn't extend over the
  354.         add     ax, clippedwidth    ; right clipping boundry, then we
  355.         dec     ax                  ; don't need to clip the right, so we
  356.         cmp     ax, cliprt          ; can jump over the right clip code.
  357.         jle     s noclipright2
  358.  
  359.         mov     ax, cliprt          ; clip off the right by reducing the
  360.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  361.         inc     ax                  ; extend over the right clipping
  362.         mov     clippedwidth, ax    ; boundry.
  363.  
  364.         ;calculate starting video address
  365. noclipright2:
  366.         movsx   edi, desty          ; we are going to set edi to start point
  367.         imul    edi, xactual/4
  368.         movsx   eax, destx          ; the offset edi is
  369.         mov     cx, ax              ; calculated by:
  370.         shr     eax, 2              ; edi = y*80+x/2
  371.         add     eax, current_page
  372.         add     edi,eax             ; edi is ready!
  373.  
  374.         mov     dx, sc_index+1      ; point the vga sequencer to the map
  375. ;       mov     al, map_mask        ; mask register, so that we only need
  376. ;       out     dx, al              ; to send out 1 byte per column.
  377.  
  378. ;       inc     dx                  ; move to the sequencer's data register.
  379.         and     cx, 3               ; calculate the starting plane. this is
  380.         mov     al, 11h             ; just:
  381.         shl     al, cl              ; plane =  (11h << (x and 3))
  382.         out     dx, al              ; select the first plane.
  383.  
  384.         movzx   ecx, sourcewidth     ; use cx for source width
  385.         mov     xad, ecx
  386.         shl     sourcewidth,1
  387.  
  388.         align   16                  ; since this point gets jumped to a lot,
  389.                                     ; make sure that it is dword aligned.
  390. rowloop2:
  391.         push    esi                 ; save the starting source index
  392.         push    edi                 ; save the starting dest index
  393.         push    ax                  ; save the current plane mask
  394.         push    bp                  ; save the current base pointer
  395.  
  396.         mov     cx, clippedheight   ; use al for row counter (0-239)
  397.         mov     bx, decisiony       ; use bx for decision variable
  398.         mov     dx, sourceheight    ; use dx for source height * 2
  399.         shl     dx, 1
  400.         mov     bp, destheight      ; use bp for dest height * 2
  401.         shl     bp, 1
  402.         mov     ah, [esi]           ; get the first source pixel
  403.         or      ah,ah
  404.         jz      s null_loop         ; if zero, perform null loop
  405.  
  406.         align   4                   ; common jump point... align for speed.
  407. columnloop2:
  408.         mov     [edi], ah           ; draw a pixel
  409.         dec     cx                  ; decrement line counter
  410.         jz      s donewithcol2      ; see if we're done with this column
  411.         add     edi, xactual/4      ; go on to the next screen row
  412.         add     bx, dx              ; increment the decision variable
  413.         js      s columnloop2       ; draw this source pixel again
  414.  
  415. incsourcerow2:
  416.         add     esi, xad            ; move to the next source pixel
  417.         sub     bx, bp              ; decrement the decision variable
  418.         jns     s incsourcerow2     ; see if we need to skip another source pixel
  419.         mov     ah, [esi]           ; get the next source pixel
  420.         cmp     ah,0
  421.         jz      s null_loop
  422.         jmp     s columnloop2       ; start drawing this pixel
  423.  
  424. donewithcol2:
  425.         pop     bp                  ; restore bp to access variables
  426.         pop     ax                  ; restore al = plane mask
  427.         pop     edi                 ; restore di to top row of screen
  428.         pop     esi                 ; restore si to top row of source bits
  429.  
  430.         rol     al, 1               ; move to next plane
  431.         adc     edi, 0              ; go on to next screen column
  432.         mov     dx, sc_data         ; tell the vga what column we're in
  433.         out     dx, al              ; by updating the map mask register
  434.  
  435.         mov     bx, decisionx       ; use bx for the x decision variable
  436.         add     bx, sourcewidth     ; increment the x decision variable
  437.         js      s nextcol2          ; jump if we're still in the same source col.
  438.         mov     dx, destwidth       ; dx = w * 2
  439.         shl     dx, 1
  440. incsourcecol2:
  441.         inc     esi                 ; move to next source column
  442.         sub     bx, dx              ; decrement x decision variable
  443.         jns     s incsourcecol2     ; see if we skip another source column
  444. nextcol2:
  445.         mov     decisionx, bx       ; free up bx for colloop
  446.         dec     clippedwidth        ; if we're not at last column
  447.         jnz     rowloop2            ;    then do another column
  448. done2:
  449.         ret                         ; we're done!
  450.  
  451.         align   16                  ; common jump point... align for speed.
  452. null_loop:
  453.         dec     cx                  ; decrement line counter
  454.         jz      s donewithcol2      ; see if we're done with this column
  455.         add     edi, xactual/4      ; go on to the next screen row
  456.         add     bx, dx              ; increment the decision variable
  457.         js      s null_loop         ; perform more increments
  458.         jmp     s incsourcerow2
  459.  
  460. ; draw repeated bit map.  good for backgrounds in menus and title  screens.
  461. ; routine is NOT intended for animation because it is slow. uses scale routine
  462. ; because scale routine clips bitmaps.  sloppy routine just draws all over the
  463. ; place and lets the scale clip borders handle the rest.
  464. ;
  465. ; repeat_bitmap (seg bitmap, x1%, y1%, x2%, y2%)
  466. ;
  467. ; remember: first two words of bitmap define width and height
  468.  
  469. rb_stack   struc
  470.      rb_wide    dw  ?   ; height and width of bitmap
  471.      rb_height  dw  ?
  472.      rb_curx    dw  ?   ; current bitmap location
  473.      rb_cury    dw  ?
  474.      rb_oldy2   dw  ?   ; old cliping borders save
  475.      rb_oldx2   dw  ?
  476.      rb_oldy1   dw  ?
  477.      rb_oldx1   dw  ?
  478.                 dd  ?x3 ; edi, esi, ebp
  479.                 dd  ?   ; caller
  480.      rb_y2      dw  ?   ; y2
  481.      rb_x2      dw  ?   ; x2
  482.      rb_y1      dw  ?   ; y1
  483.      rb_x1      dw  ?   ; x1
  484.      rb_bitmap  dd  ?   ; offset to bitmap
  485. rb_stack   ends
  486.  
  487. repeat_bitmap:
  488.            push ebp esi edi       ; preserve important registers
  489.            sub esp, 16            ; allocate workspace
  490.            mov ebp, esp           ; set up stack frame
  491.  
  492.            mov ax,cliplt          ; save old borders just in case
  493.            mov [ebp].rb_oldx1,ax
  494.            mov ax,cliprt
  495.            mov [ebp].rb_oldx2,ax
  496.            mov ax,cliptp
  497.            mov [ebp].rb_oldy1,ax
  498.            mov ax,clipbt
  499.            mov [ebp].rb_oldy2,ax
  500.  
  501.            mov x1,4
  502.  
  503.            mov ax,[ebp].rb_x1     ; set new borders for clipping
  504.            mov cliplt,ax
  505.            mov ax,[ebp].rb_x2
  506.            mov cliprt,ax
  507.            mov ax,[ebp].rb_y1
  508.            mov cliptp,ax
  509.            mov ax,[ebp].rb_y2
  510.            mov clipbt,ax
  511.  
  512.            mov [ebp].rb_curx,0    ; we could start at x1,y1 but this
  513.            mov [ebp].rb_cury,0    ; will make offset backgrounds
  514.  
  515.            mov esi,[ebp].rb_bitmap
  516.            mov bitmap,esi
  517.            lodsw                  ; set destination width same as original
  518.            mov [ebp].rb_wide,ax
  519.            lodsw
  520.            mov [ebp].rb_height,ax
  521. nextline:
  522.            mov ax,[ebp].rb_wide
  523.            mov destwidth,ax
  524.            mov ax,[ebp].rb_height
  525.            mov destheight,ax
  526.  
  527.            mov ax,[ebp].rb_curx
  528.            mov destx,ax
  529.            mov ax,[ebp].rb_cury
  530.            mov desty,ax
  531.  
  532.            push ebp
  533.            call xscale2           ; draw a transparent bitmap
  534.            pop ebp
  535.  
  536.            mov ax,[ebp].rb_curx
  537.            add ax,[ebp].rb_wide
  538.            mov [ebp].rb_curx,ax
  539.            cmp ax,[ebp].rb_x2
  540.            jle s nextline
  541.  
  542.            mov [ebp].rb_curx,0
  543.  
  544.            mov ax,[ebp].rb_cury
  545.            add ax,[ebp].rb_height
  546.            mov [ebp].rb_cury,ax
  547.            cmp ax,[ebp].rb_y2
  548.            jle s nextline
  549.  
  550.            mov ax,[ebp].rb_oldx1
  551.            mov cliplt,ax
  552.            mov ax,[ebp].rb_oldx2
  553.            mov cliprt,ax
  554.            mov ax,[ebp].rb_oldy1
  555.            mov cliptp,ax
  556.            mov ax,[ebp].rb_oldy2
  557.            mov clipbt,ax
  558.  
  559.            add esp, 16
  560.            pop edi esi ebp
  561.            ret 12
  562.  
  563. ; draw transparent bitmap using 1/4 xmode method. - draws every 4 pixels alike.
  564. ; great  for  explosions/smoke  where  the  bitmap  does  not have to be  very
  565. ; accuratly drawn - much faster
  566.  
  567. done4:  ret
  568.  
  569. tdraw_scale4:
  570.         mov bitmap,esi
  571.         mov destwidth,ax
  572.         mov destheight,bx
  573.         mov destx,cx
  574.         mov desty,dx
  575.  
  576. xscale4:
  577.         cmp     destwidth, 2        ; if destination width is less than 2
  578.         jl      s done4             ;     then don't draw it.
  579.  
  580.         cmp     destheight, 2       ; if destination height is less than 2
  581.         jl      s done4             ;     then don't draw it.
  582.  
  583.         mov     ax, desty           ; if it is completely below the
  584.         cmp     ax, clipbt          ; lower clip bondry,
  585.         jg      s done4             ;     then don't draw it.
  586.  
  587.         add     ax, destheight      ; if it is above clip boundries
  588.         dec     ax                  ;     then don't draw it.
  589.         cmp     ax, cliptp
  590.         jl      s done4
  591.  
  592.         mov     ax, destx           ; if it is to the right of the
  593.         mov     cx, cliprt          ; right clip boundry
  594.         cmp     ax, cliprt          ;     then don't draw it.
  595.         jg      s done4
  596.  
  597.         add     ax, destwidth       ; if it is completely to the left
  598.         dec     ax                  ; of the left clip boundry,
  599.         cmp     ax, cliplt          ;     then don't draw it.
  600.         jl      s done4
  601.  
  602.         mov     esi, bitmap         ; make esi point to bitmap data
  603.         lodsw                       ; get source x width
  604.         mov     sourcewidth,ax
  605.         lodsw                       ; get source y height
  606.         mov     sourceheight,ax
  607.  
  608.         mov     ax, destwidth       ; clippedwidth is initially set to
  609.         mov     clippedwidth, ax    ; the requested dest width.
  610.  
  611.         shl     ax,1                ; initialize the x decision var
  612.         neg     ax                  ; to be -2*destwidth
  613.         mov     decisionx, ax       ;
  614.  
  615.         mov     ax, destheight      ; clippedheight is initially set to
  616.         mov     clippedheight, ax   ; the requested dest size.
  617.  
  618.         shl     ax,1                ; initialize the y decision var
  619.         neg     ax                  ; to be -2*destheight
  620.         mov     decisiony, ax       ;
  621.  
  622.         movsx   eax, cliptp         ; if y is below the top
  623.         mov     edx, eax            ; clipping boundry, then we don't
  624.         sub     dx, desty           ; need to clip the top, so we can
  625.         js      s notopclip4        ; jump over the clipping stuff.
  626.  
  627.         mov     desty, ax           ; this block performs clipping on the
  628.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  629.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  630.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  631.         mov     eax, ecx            ; gonna try to explain what it's doing.
  632.         cdq                         ; but i can tell you what results from
  633.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  634.         idiv    ebx                 ; to start at the right clipped row.
  635.         movsx   edx, sourcewidth    ; y is moved to the top clip
  636.         imul    edx, eax            ; boundry. clippedheight is lowered since
  637.         add     esi, edx            ; we won't be drawing all the requested
  638.         imul    eax, ebx            ; rows. esi is changed to point over
  639.         sub     ecx, eax            ; the bitmap data that is clipped off.
  640.         sub     ecx, ebx            ;
  641.         shl     ecx, 1              ;
  642.         mov     decisiony, cx       ; <end of top clipping block >
  643.  
  644. notopclip4:
  645.         mov     ax, desty           ; if the bitmap doesn't extend over the
  646.         add     ax, clippedheight   ; bottom clipping boundry, then we
  647.         dec     ax                  ; don't need to clip the bottom, so we
  648.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  649.         jle     s nobottomclip4
  650.  
  651.         mov     ax, clipbt          ; clip off the bottom by reducing the
  652.         sub     ax, desty           ; clippedheight so that the bitmap won't
  653.         inc     ax                  ; extend over the lower clipping
  654.         mov     clippedheight, ax   ; boundry.
  655.  
  656. nobottomclip4:
  657.         movsx   eax, cliplt         ; if x is to the left of the
  658.         mov     edx, eax            ; top clipping boundry, then we don't
  659.         sub     dx, destx           ; need to clip the left, so we can
  660.         js      s noleftclip4       ; jump over the clipping stuff.
  661.  
  662.         mov     destx, ax           ; this block performs clipping on the
  663.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  664.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  665.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  666.         mov     eax, ecx            ; gonna try to explain what it's doing.
  667.         cdq                         ; but i can tell you what results from
  668.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  669.         idiv    ebx                 ; to start at the right clipped column.
  670.         add     esi, eax            ; x is moved to the left clip
  671.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  672.         sub     ecx, eax            ; we won't be drawing all the requested
  673.         sub     ecx, ebx            ; cols. esi is changed to point over
  674.         shl     ecx, 1              ; the bitmap data that is clipped off.
  675.         mov     decisionx, cx       ; <end of left clipping block >
  676.  
  677. noleftclip4:
  678.         mov     ax, destx           ; if the bitmap doesn't extend over the
  679.         add     ax, clippedwidth    ; right clipping boundry, then we
  680.         dec     ax                  ; don't need to clip the right, so we
  681.         cmp     ax, cliprt          ; can jump over the right clip code.
  682.         jle     s noclipright4
  683.  
  684.         mov     ax, cliprt          ; clip off the right by reducing the
  685.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  686.         inc     ax                  ; extend over the right clipping
  687.         mov     clippedwidth, ax    ; boundry.
  688.  
  689.         ;calculate starting video address
  690. noclipright4:
  691.         movsx   edi, desty          ; we are going to set edi to start point
  692.         imul    edi, xactual/4
  693.         movsx   eax, destx          ; the offset edi is
  694.         mov     cx, ax              ; calculated by:
  695.         shr     eax, 2              ; edi = y*80+x/2
  696.         add     eax, current_page
  697.         add     edi,eax             ; edi is ready!
  698.  
  699.         mov     dx, sc_index+1      ; point the vga sequencer to the map
  700. ;       mov     al, map_mask        ; mask register, so that we only need
  701. ;       out     dx, al              ; to send out 1 byte per column.
  702.  
  703. ;       inc     dx                  ; move to the sequencer's data register.
  704.         mov     al, all_planes
  705.         out     dx, al              ; select the first plane.
  706.  
  707.         movzx   ecx, sourcewidth    ; use cx for source width
  708.         mov     xad, ecx
  709.  
  710.         shl     sourcewidth,1+2     ; 4 times as fast
  711.         shr     clippedwidth,2      ; 1/4 of the plots
  712.  
  713.         cmp     clippedwidth,0      ; check if <4 wide
  714.         jne     s rowloop4
  715.         inc     clippedwidth
  716.  
  717.         align   16                  ; since this point gets jumped to a lot,
  718.                                     ; make sure that it is dword aligned.
  719. rowloop4:
  720.         push    esi                 ; save the starting source index
  721.         push    edi                 ; save the starting dest index
  722.         push    bp                  ; save the current base pointer
  723.  
  724.         mov     cx, clippedheight   ; use al for row counter (0-239)
  725.         mov     bx, decisiony       ; use bx for decision variable
  726.         mov     dx, sourceheight    ; use dx for source height * 2
  727.         shl     dx, 1
  728.         mov     bp, destheight      ; use bp for dest height * 2
  729.         shl     bp, 1
  730.         mov     ah, [esi]           ; get the first source pixel
  731.         or      ah,ah
  732.         jz      s null_loop4        ; if zero, perform null loop
  733.  
  734.         align   4                   ; common jump point... align for speed.
  735. columnloop4:
  736.         mov     [edi], ah           ; draw a pixel
  737.         dec     cx                  ; decrement line counter
  738.         jz      s donewithcol4      ; see if we're done with this column
  739.         add     edi, xactual/4      ; go on to the next screen row
  740.         add     bx, dx              ; increment the decision variable
  741.         js      s columnloop4       ; draw this source pixel again
  742.  
  743. incsourcerow4:
  744.         add     esi, xad            ; move to the next source pixel
  745.         sub     bx, bp              ; decrement the decision variable
  746.         jns     s incsourcerow4     ; see if we need to skip another source pixel
  747.         mov     ah, [esi]           ; get the next source pixel
  748.         or      ah,ah
  749.         jz      s null_loop4
  750.         jmp     s columnloop4       ; start drawing this pixel
  751.  
  752. donewithcol4:
  753.         pop     bp                  ; restore bp to access variables
  754.         pop     edi                 ; restore di to top row of screen
  755.         pop     esi                 ; restore si to top row of source bits
  756.  
  757.         add     edi, 1              ; go on to next screen column
  758.  
  759.         mov     bx, decisionx       ; use bx for the x decision variable
  760.         add     bx, sourcewidth     ; increment the x decision variable
  761.         mov     dx, destwidth       ; dx = w * 2
  762.         shl     dx, 1
  763. incsourcecol4:
  764.         inc     esi                 ; move to next source column
  765.         sub     bx, dx              ; decrement x decision variable
  766.         jns     s incsourcecol4     ; see if we skip another source column
  767. nextcol4:
  768.         mov     decisionx, bx       ; free up bx for colloop
  769.         dec     clippedwidth        ; if we're not at last column
  770.         jnz     rowloop4            ;    then do another column
  771.  
  772.         ret                         ; we're done!
  773.  
  774.         align   16                  ; common jump point... align for speed.
  775. null_loop4:
  776.         dec     cx                  ; decrement line counter
  777.         jz      s donewithcol4      ; see if we're done with this column
  778.         add     edi, xactual/4      ; go on to the next screen row
  779.         add     bx, dx              ; increment the decision variable
  780.         js      s null_loop4        ; perform more increments
  781.         jmp     s incsourcerow4
  782.  
  783.